package cn.edu.fzu.delivery.common;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 * 逗号分隔的参数集合接受
 */
public class MultiArgumentHandler implements HandlerMethodArgumentResolver {

    private static final String METHOD_NAME  = "valueOf";

    private static final String SEPARATOR    = ",";

    private static final Object EMPTY_OBJECT = new Object();

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        //仅处理集合类型的参数
        return List.class.isAssignableFrom(methodParameter.getParameterType());
    }


    /**
     * 需要获取valueOf方法来实现转型,拿Long类型举例
     * 当Controller类中使用List<Long>来接受的时候,即使未使用valueOf发现也能接受,但list中的元素还是String类型,相当于泛型擦除了
     * 当使用遍历该list时就会出现类型转换异常
     */
    @Override
    @SuppressWarnings("unchecked")
    public List resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
                                NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory)
            throws Exception {
        String name = methodParameter.getParameterName();
        ParameterizedType type = (ParameterizedType) methodParameter.getGenericParameterType();
        Class actualType = (Class) type.getActualTypeArguments()[0];
        Method valueOf = actualType.getDeclaredMethod(METHOD_NAME, String.class);

        HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest();
        String parameter = request.getParameter(name);

        List list = new LinkedList();
        if (StringUtils.isNotBlank(parameter)) {
            String[] params = StringUtils.split(parameter, SEPARATOR);
            for (String param : params) {
                if (StringUtils.isNotBlank(param)) {
                    if (valueOf != null) {
                        list.add(valueOf.invoke(EMPTY_OBJECT, param));
                    } else {
                        list.add(param);
                    }
                }
            }
        }
        return list;
    }
}
